<!DOCTYPE html>
<html>

<head>
    <meta charset='utf-8'>
    <meta http-equiv='X-UA-Compatible' content='IE=edge'>
    <title>批量生成数据</title>
    <meta name='viewport' content='width=device-width, initial-scale=1'>
    <link rel='stylesheet' type='text/css' media='screen'
          href='https://lf26-cdn-tos.bytecdntp.com/cdn/expire-1-M/element-ui/2.15.7/theme-chalk/index.min.css'>
    <script src='https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-M/vue/2.6.14/vue.min.js'></script>
    <script src='https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-M/element-ui/2.15.7/index.min.js'></script>
    <script src='https://lf9-cdn-tos.bytecdntp.com/cdn/expire-1-M/axios/0.26.0/axios.min.js'></script>
</head>

<body>
<div id="app">
    <el-form inline>
        <el-card :header="'数据库'+(connected?(db.ip+':'+db.port+'已连接，可以选择实例与表了'):'')">
            <template v-if="!connected">
                <el-form-item label="IP">
                    <el-input v-model="db.ip"></el-input>
                </el-form-item>
                <el-form-item label="端口">
                    <el-input v-model="db.port"></el-input>
                </el-form-item>
                <el-form-item label="用户">
                    <el-input v-model="db.username"></el-input>
                </el-form-item>
                <el-form-item label="密码">
                    <el-input type="password" v-model="db.password"></el-input>
                </el-form-item>
                <el-button v-if="!connected" type="primary" @click="connect">连接</el-button>
            </template>
            <template v-else>
                <el-form-item label="库名">
                    <el-select v-model="inst.schema" @change="handleSchemaChange" clearable filterable>
                        <el-option v-for="s in schemaOptions" :key="s" :value="s" :label="s"></el-option>
                    </el-select>
                </el-form-item>
                <el-form-item v-if="inst.schema" label="表名">
                    <el-select v-model="inst.table" @change="handleTableChange" clearable filterable>
                        <el-option v-for="s in tableOptions" :key="s[0]" :value="s[0]" :label="s[0]"></el-option>
                    </el-select>
                </el-form-item>
                <el-form-item v-if="connected && !!inst.table">
                    生成记录数：
                    <el-input-number min="1" setp="1" placeholder="生成数量" v-model="count" size="small">
                    </el-input-number>
                    <el-button style="margin-left: 30px;" :loading="generating" @click="generateData"
                               :disabled="count<=0">开始生成数据
                    </el-button>
                </el-form-item>
                <br>
            </template>
        </el-card>
    </el-form>
    <el-table v-show="connected && !!inst.table" :data="columns">
        <el-table-column label="字段名" prop="column_name" width="320"></el-table-column>
        <el-table-column label="注释" prop="column_comment" width="320"></el-table-column>
        <el-table-column label="类型" prop="data_type" width="80">
            <template scope="scope">
                <template v-if="stringTypes.includes(scope.row.data_type)">字符串</template>
                <template v-if="numberTypes.includes(scope.row.data_type)">数字</template>
                <template v-if="dateTypes.includes(scope.row.data_type)">日期</template>
            </template>
        </el-table-column>
        <el-table-column label="操作" prop="column_name">
            <template scope="scope">
                <el-select v-model="scope.row.action_type" placeholder="生成类型" size="small"
                           :disabled="scope.row.action_type==3">
                    <el-option :key="1" :value="1" label="固定值"></el-option>
                    <el-option :key="2" :value="2" label="根据规则生成值"></el-option>
                    <el-option :key="2" :value="5" label="关联其它表字段"></el-option>
                    <el-option :key="2" :value="6" label="根据SQL生成"></el-option>
                    <el-option v-if="scope.row.action_type==3" :key="3" :value="3" label="自动生成"
                               disabled></el-option>
                    <el-option :key="4" :value="4" label="空值" :disabled="scope.row.is_nullable!='YES'"></el-option>
                </el-select>

                <el-input v-if="scope.row.action_type==1" v-model="scope.row.fixed_string" style="width: 75%;"
                          placeholder="填写固定值（如果为日期，格式：yyyy-MM-dd HH:mm:ss），可提供多个可选项，逗号分隔">
                </el-input>

                <el-input v-if="scope.row.action_type==5" v-model="scope.row.ref_table_col" style="width: 75%;"
                          placeholder="填写关联表字段，只可以关联同一个数据库实例上的表，格式：库名.表名.字段名，与当前表在同一个库时，库名可以省略">
                </el-input>

                <el-input v-if="scope.row.action_type==6" v-model="scope.row.sql" style="width: 75%;"
                          placeholder="填写查询sql语句，可以通过 ${字段名(不可以是主键)} 的写法关联当前表的其它字段值，只取select的结果中第一个字段的值">
                </el-input>

                <template v-if="stringTypes.includes(scope.row.data_type) && scope.row.action_type==2">
                        <span style="width: 280px; border: 1px solid lightgray; margin-right: 10px;">
                            <el-radio v-model="scope.row.only" label="all">不限制</el-radio>
                            <el-radio v-model="scope.row.only" label="letter">英文字母</el-radio>
                            <el-radio v-model="scope.row.only" label="number">纯数字</el-radio>
                        </span>
                    定长(不包含前后缀部分):
                    <el-input-number v-model="scope.row.length" size="small" step="1"
                                     :min="1" :max="scope.row.character_maximum_length"
                                     placeholder="请填写生成字符串长度">
                    </el-input-number>
                    <br>
                    前缀:
                    <el-input v-model="scope.row.prefix_string" style="width: 45%;"
                              placeholder="请填写前缀，可提供多个可选项，逗号分隔"></el-input>
                    后缀:
                    <el-input v-model="scope.row.suffix_string" style="width: 45%;"
                              placeholder="请填写后缀，可提供多个可选项，逗号分隔"></el-input>
                </template>

                <template v-if="numberTypes.includes(scope.row.data_type) && scope.row.action_type==2">
                    最小值:
                    <el-input-number v-model="scope.row.min" size="small" placeholder="请填写最小值"></el-input-number>
                    最大值:
                    <el-input-number v-model="scope.row.max" size="small" placeholder="请填写最大值"></el-input-number>
                    小数位数:
                    <el-input-number v-model="scope.row.scale" size="small"
                                     placeholder="请填写小数位数"></el-input-number>
                </template>

                <template v-if="dateTypes.includes(scope.row.data_type) && scope.row.action_type==2">
                    开始日期:
                    <el-date-picker v-model="scope.row.min" type="datetime" placeholder="选择开始日期时间">
                    </el-date-picker>
                    结束日期:
                    <el-date-picker v-model="scope.row.max" type="datetime"
                                    placeholder="选择结束日期时间">
                    </el-date-picker>
                </template>

            </template>
        </el-table-column>
    </el-table>
</div>
</body>
<script>
    const cookie_db_config_key = "batch_generate_table_data_db_config"

    function setCookie(cname, cvalue, exdays) {
        const d = new Date();
        d.setTime(d.getTime() + ((exdays||1) * 24 * 60 * 60 * 1000));
        const expires = "expires=" + d.toGMTString();
        document.cookie = cname + "=" + cvalue + "; " + expires;
    }

    function getCookie(cname) {
        const name = cname + "=";
        const ca = document.cookie.split(';');
        for (let i = 0; i < ca.length; i++) {
            const c = ca[i].trim();
            if (c.indexOf(name) === 0) {
                return c.substring(name.length, c.length);
            }
        }
        return "";
    }

    const data_service = axios.create({
        baseURL: 'http://localhost:9901/batch/data',
        timeout: 5000,
        headers: {
            'Content-Type': 'application/json',
            'token': localStorage.getItem('current_db_token')
        }
    });

    new Vue({
        el: '#app',
        data() {
            return {
                connected: false,
                db: {
                    ip: null,
                    port: 3306,
                    username: null,
                    password: null
                },
                inst: {
                    schema: null,
                    table: null
                },
                schemaOptions: [],
                tableOptions: [],
                columns: [],
                stringTypes: ['char', 'varchar', 'text', 'mediumtext', 'longtext'],
                numberTypes: ['bit', 'bigint', 'decimal', 'double', 'float', 'int', 'smallint', 'tinyint'],
                dateTypes: ['datetime', 'time', 'timestamp'],
                generating: false,
                count: 100,
                define_data: {
                    // 操作类型 1固定值，2定义值，3自动生成，4空值
                    action_type: 1,
                    // 前缀
                    prefix: false,
                    prefix_string: null,
                    // 后缀
                    suffix: false,
                    suffix_string: null,
                    // 固定值
                    fixed: false,
                    fixed_string: null,
                    // 值长度
                    length: null,
                    // 最小值
                    min: null,
                    // 最大值
                    max: null,
                    // 置空
                    set_null: false,
                    // 小数位数
                    scale: null,
                    // 字符串出只出现某类字符
                    only: null,
                    // 关联其它表字段值
                    ref_table_col: null,
                    // 通过sql生成值
                    sql: null
                }
            }
        },
        mounted() {
            const dbConfig = getCookie(cookie_db_config_key)
            if (dbConfig) {
                this.db = JSON.parse(dbConfig)
            }
        },
        methods: {
            connect() {
                const connectionInfo = {
                    host: this.db.ip,
                    port: this.db.port,
                    username: this.db.username,
                    password: this.db.password
                }
                data_service.post('/connect', connectionInfo).then(res => {
                    if (res.data) {
                        this.connected = true
                        localStorage.setItem("current_db_token", res.data)
                        setCookie(cookie_db_config_key, JSON.stringify(this.db), 7)
                        this.getSchemaList()
                    } else {
                        this.$message.error('连接失败')
                    }
                }).catch(err => this.$message.error('连接异常：' + err))
            },
            getSchemaList(token) {
                data_service.get('/schema/list').then(res => {
                    this.schemaOptions = res.data
                })
            },
            handleSchemaChange(schema) {
                if (!schema) return
                data_service.get('/table/list/' + schema).then(res => {
                    this.columns = []
                    this.table = null
                    this.tableOptions = []
                    this.tableOptions = res.data
                })
            },
            handleTableChange(table) {
                if (!table) return
                data_service.get('/column/list/' + this.inst.schema + '/' + table).then(res => {
                    this.columns = res.data
                    this.columns.forEach(e => {
                        for (let k in this.define_data) {
                            this.$set(e, k, this.define_data[k])
                        }
                        if ((e.column_key === 'PRI' && e.extra === 'auto_increment')) {
                            this.$set(e, 'action_type', 3)
                        }
                    });
                })
            },
            generateData() {
                this.generating = true
                data_service.post('/generate/' + this.count, this.columns).then(res => {
                    this.generating = false
                    this.$message.success("生成成功")
                }).catch(err => this.generating = false)
            }
        }
    })
</script>

</html>